﻿//===============================================================================
// Microsoft Innovation Centre - Western Europe
// Copyright (c) 2008 Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Microsoft.WVB.Framework;
using Microsoft.WVB.Silverlight.Infrastructure;
using System.Windows.Controls.Primitives;
using Microsoft.Practices.Composite.Events;

namespace Microsoft.WVB.UI
{
    [TemplatePart(Name = ExplorerBase.HeaderElementName, Type = typeof(Panel)),
    TemplatePart(Name = ExplorerBase.BodyElementName, Type = typeof(Panel)),
    TemplatePart(Name = ExplorerBase.NavigationElementName, Type = typeof(Panel)),
    TemplatePart(Name = ExplorerBase.NavigationElementName, Type = typeof(ButtonBase))]
    [TemplateVisualState(GroupName = VisualStates.GroupCommon, Name = VisualStates.StateNormal),
    TemplateVisualState(GroupName = VisualStates.GroupCommon, Name = VisualStates.StateIconed)]
    public class ExplorerBase : ListBox
    {
        private const string HeaderElementName = "HeaderElement";
        private const string BodyElementName = "BodyElement";
        private const string NavigationElementName = "NavigationElement";
        private const string MinimizeElementName = "MinimizeElement";

        private RoutedEventHandler minimizeHandler = null;
        private SelectionChangedEventHandler selectHandler = null;
        
        protected Panel Header { get; set; }
        protected Panel Body { get; set; }
        protected Panel Navigation { get; set; }
        protected ButtonBase MinimizeButton { get; set; } 

        public event RoutedEventHandler CurrentStateChanged;
        public event RoutedEventHandler IsBufferingChanged;

        public IExplorerModel ViewModel { get; private set; }

        public ExplorerState CurrentState
        {
            get { return (ExplorerState)GetValue(CurrentStateProperty); }
            set { SetValue(CurrentStateProperty, value); }
        }
        public static readonly DependencyProperty CurrentStateProperty = null;

        public Boolean IsBuffering
        {
            get { return (Boolean)GetValue(IsBufferingProperty); }
            set { SetValue(IsBufferingProperty, value); }
        }
        public static readonly DependencyProperty IsBufferingProperty = null;

        public int DisplayedItems
        {
            get { return (int)GetValue(DisplayedItemsProperty); }
            set { SetValue(DisplayedItemsProperty, value); }
        }
        public static readonly DependencyProperty DisplayedItemsProperty = null;

        static ExplorerBase()
        {
            CurrentStateProperty = DependencyProperty.Register("CurrentState", typeof(ExplorerState), typeof(ExplorerBase), new PropertyMetadata(ExplorerState.Iconed, new PropertyChangedCallback(OnCurrentStateChanged)));
            IsBufferingProperty = DependencyProperty.Register("IsBuffering", typeof(Boolean), typeof(ExplorerBase), new PropertyMetadata(false, new PropertyChangedCallback(OnIsBufferingChanged)));
            DisplayedItemsProperty = DependencyProperty.Register("DisplayedItems", typeof(int), typeof(ExplorerBase), new PropertyMetadata(9, new PropertyChangedCallback(OnDisplayedItemsChanged)));
        }

        public ExplorerBase()
            : base()
        {
            this.DefaultStyleKey = typeof(ExplorerBase);

            if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
            {
                ViewModel = IoC.GetCreate<IExplorerModel>();
                DataContext = ViewModel;

                Binding itemsBinding = new Binding("DisplayItems");
                itemsBinding.Source = ViewModel;
                itemsBinding.Mode = BindingMode.OneWay;
                this.SetBinding(ExplorerBase.ItemsSourceProperty, itemsBinding);

                Binding bufferBinding = new Binding("IsBuffering");
                bufferBinding.Source = ViewModel;
                bufferBinding.Mode = BindingMode.OneWay;
                this.SetBinding(ExplorerBase.IsBufferingProperty, bufferBinding);

                if (selectHandler == null)
                {
                    selectHandler = delegate(object sender, SelectionChangedEventArgs e)
                    {
                        if (this.SelectedItem != null)
                            ViewModel.DrillDown(e.AddedItems[0]);
                    };
                }
                this.SelectionChanged += selectHandler;

                if (minimizeHandler == null)
                {
                    minimizeHandler = delegate(object sender, RoutedEventArgs e)
                    {
                        if (CurrentState == ExplorerState.Normal)
                        {
                            this.CurrentState = ExplorerState.Iconed;
                            this.SetValue(Canvas.ZIndexProperty, 0);
                            ViewModel.ResetData();
                        }
                    };
                }

                IEventAggregator ag = IoC.GetCreate<IEventAggregator>();
                ag.GetEvent<ExplorerMinimizeEvent>().Subscribe(this.AutoMinimize, Microsoft.Practices.Composite.Wpf.Events.ThreadOption.UIThread, true);
            }
        }

        public virtual void AutoMinimize(Control control)
        {
            if (control != (Control)this)
            {
                minimizeHandler.Invoke(this, new RoutedEventArgs());
            }
        }

        static void OnCurrentStateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((ExplorerBase)d).OnCurrentStateChanged((ExplorerState)e.OldValue, (ExplorerState)e.NewValue);
        }

        protected virtual void OnCurrentStateChanged(ExplorerState oldValue, ExplorerState newValue)
        {
            if (CurrentStateChanged != null)
                this.CurrentStateChanged(this, new RoutedEventArgs());

            UpdateVisualState();
        }

        static void OnIsBufferingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((ExplorerBase)d).OnIsBufferingChanged((Boolean)e.OldValue, (Boolean)e.NewValue);
        }

        protected virtual void OnIsBufferingChanged(Boolean oldValue, Boolean newValue)
        {
            if (IsBufferingChanged != null)
                this.IsBufferingChanged(this, new RoutedEventArgs());

            UpdateVisualState();
        }

        static void OnDisplayedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((ExplorerBase)d).OnDisplayedItemsChanged((int)e.OldValue, (int)e.NewValue);
        }

        protected virtual void OnDisplayedItemsChanged(int oldValue, int newValue)
        {
            if (oldValue != newValue)
            {
                if (ViewModel != null)
                    ViewModel.SetItemsNumberToDisplay(newValue);
            }
        }

        internal void UpdateVisualState()
        {
            this.ChangeVisualState(true);
        }

        private void ChangeVisualState(bool useTransitions)
        {
            switch (this.CurrentState)
            {
                case ExplorerState.Normal:
                    {
                        VisualStates.GoToState(this, useTransitions, new String[] { VisualStates.StateNormal });
                        break;
                    }

                case ExplorerState.Iconed:
                    {
                        VisualStates.GoToState(this, useTransitions, new String[] { VisualStates.StateIconed });
                        break;
                    }
                
                default:
                    break;
            }
        }

        public override void OnApplyTemplate()
        {
            
            base.OnApplyTemplate();

            Header = base.GetTemplateChild(ExplorerBase.HeaderElementName) as Panel;
            Body = base.GetTemplateChild(ExplorerBase.BodyElementName) as Panel;
            Navigation = base.GetTemplateChild(ExplorerBase.NavigationElementName) as Panel;
            MinimizeButton = base.GetTemplateChild(ExplorerBase.MinimizeElementName) as ButtonBase;

            if (MinimizeButton != null)
            {                
                MinimizeButton.Click += minimizeHandler;
            }
        }
    }
}
